package com.ibm.util;

/**
 * @author Yaoliang Chen
 * @version May 20, 2014 the byte utility
 */

public class ByteUtil {

	public static byte[] longBytes(long ldata, int len){
		byte[] data = new byte[len];
		setLongBytes(data, 0, ldata, len);
		return data;
	}
	
	public static void setShortBytes(byte[] bytes, int offset, long data) {
		bytes[offset + 0] = (byte) (data & 0xff);
		bytes[offset + 1] = (byte) ((data & 0xff00) >> 8);

	}

	public static void setIntBytes(byte[] bytes, int offset, long idata) {
		bytes[offset + 0] = (byte) (idata & 0xff);
		bytes[offset + 1] = (byte) ((idata & 0xff00) >> 8);
		bytes[offset + 2] = (byte) ((idata & 0xff0000) >> 16);
		bytes[offset + 3] = (byte) ((idata & 0xff000000) >> 24);

	}

	public static void setLongBytes(byte[] bytes, int offset, long ldata) {
		bytes[offset + 0] = (byte) (ldata & 0xff);
		bytes[offset + 1] = (byte) ((ldata >> 8) & 0xff);
		bytes[offset + 2] = (byte) ((ldata >> 16) & 0xff);
		bytes[offset + 3] = (byte) ((ldata >> 24) & 0xff);
		bytes[offset + 4] = (byte) ((ldata >> 32) & 0xff);
		bytes[offset + 5] = (byte) ((ldata >> 40) & 0xff);
		bytes[offset + 6] = (byte) ((ldata >> 48) & 0xff);
		bytes[offset + 7] = (byte) ((ldata >> 56) & 0xff);
	}

	public static void setLongBytes(byte[] bytes, int offset, long ldata, int len) {
		if(len > 8) {
			len = 8;
		}
		switch (len) {
		case 8:
			bytes[offset + 7] = (byte) ((ldata >> 56) & 0xff);
		case 7:
			bytes[offset + 6] = (byte) ((ldata >> 48) & 0xff);
		case 6:
			bytes[offset + 5] = (byte) ((ldata >> 40) & 0xff);
		case 5:
			bytes[offset + 4] = (byte) ((ldata >> 32) & 0xff);
		case 4:
			bytes[offset + 3] = (byte) ((ldata >> 24) & 0xff);
		case 3:
			bytes[offset + 2] = (byte) ((ldata >> 16) & 0xff);
		case 2:
			bytes[offset + 1] = (byte) ((ldata >> 8) & 0xff);
		case 1:
			bytes[offset + 0] = (byte) (ldata & 0xff);
		}
		
	}

	public static void setFloatBytes(byte[] bytes, int offset, double data) {
		int idata = Float.floatToIntBits((float) data);
		bytes[offset + 0] = (byte) (idata & 0xff);
		bytes[offset + 1] = (byte) ((idata & 0xff00) >> 8);
		bytes[offset + 2] = (byte) ((idata & 0xff0000) >> 16);
		bytes[offset + 3] = (byte) ((idata & 0xff000000) >> 24);
	}

	public static void setDoubleBytes(byte[] bytes, int offset, double data) {
		long ldata = Double.doubleToLongBits(data);
		bytes[offset + 0] = (byte) (ldata & 0xff);
		bytes[offset + 1] = (byte) ((ldata >> 8) & 0xff);
		bytes[offset + 2] = (byte) ((ldata >> 16) & 0xff);
		bytes[offset + 3] = (byte) ((ldata >> 24) & 0xff);
		bytes[offset + 4] = (byte) ((ldata >> 32) & 0xff);
		bytes[offset + 5] = (byte) ((ldata >> 40) & 0xff);
		bytes[offset + 6] = (byte) ((ldata >> 48) & 0xff);
		bytes[offset + 7] = (byte) ((ldata >> 56) & 0xff);
	}

	public static Short getByte(byte[] bytes, int offset) {
		short s = (short) ((0xff & bytes[offset + 0]) | (0xff00 & (bytes[offset + 1] << 8)));
		return (s == DataTypes.BYTE_NULL ? null : s);
	}

	public static Short getShort(byte[] bytes, int offset) {
		short s = (short) ((0xff & bytes[offset + 0]) | (0xff00 & (bytes[offset + 1] << 8)));
		return (s == DataTypes.SHORT_NULL ? null : s);
	}

	public static Integer getInt(byte[] bytes, int offset) {
		int i = (0xff & bytes[offset + 0]) | (0xff00 & (bytes[offset + 1] << 8))
				| (0xff0000 & (bytes[offset + 2] << 16)) | (0xff000000 & (bytes[offset + 3] << 24));
		return (i == DataTypes.INT_NULL ? null : i);
	}

	public static Long getUInt(byte[] bytes, int offset) {
		long i = (0xff & bytes[offset + 0]) | (0xff00 & (bytes[offset + 1] << 8))
				| (0xff0000 & (bytes[offset + 2] << 16)) | (0xff000000 & (bytes[offset + 3] << 24));
		return (i == DataTypes.INT_NULL ? null : i);
	}

	public static Long getLong(byte[] bytes, int offset) {
		Long l = (0xffL & (long) bytes[offset + 0]) | (0xff00L & ((long) bytes[offset + 1] << 8))
				| (0xff0000L & ((long) bytes[offset + 2] << 16)) | (0xff000000L & ((long) bytes[offset + 3] << 24))
				| (0xff00000000L & ((long) bytes[offset + 4] << 32))
				| (0xff0000000000L & ((long) bytes[offset + 5] << 40))
				| (0xff000000000000L & ((long) bytes[offset + 6] << 48))
				| (0xff00000000000000L & ((long) bytes[offset + 7] << 56));
		return (l == DataTypes.LONG_NULL ? null : l);
	}

	public static Float getFloat(byte[] bytes, int offset) {
		Integer i = getInt(bytes, offset);
		if (i == null || i == DataTypes.FLOAT_NULL)
			return null;
		return Float.intBitsToFloat(i);
	}

	public static Double getDouble(byte[] bytes, int offset) {
		Long l = getLong(bytes, offset);
		if (l == null || l == DataTypes.DOUBLE_NULL)
			return null;
		return Double.longBitsToDouble(l);
	}

	public static void setBytes(byte[] bytes, int offset, byte[] data) {
		System.arraycopy(data, 0, bytes, offset, data.length);
	}

	public static void setSixBytesLong(byte[] bytes, int offset, long ldata) {
		bytes[offset + 0] = (byte) (ldata & 0xff);
		bytes[offset + 1] = (byte) ((ldata >> 8) & 0xff);
		bytes[offset + 2] = (byte) ((ldata >> 16) & 0xff);
		bytes[offset + 3] = (byte) ((ldata >> 24) & 0xff);
		bytes[offset + 4] = (byte) ((ldata >> 32) & 0xff);
		bytes[offset + 5] = (byte) ((ldata >> 40) & 0xff);
	}

	public static Long getSixBytesLong(byte[] bytes, int offset) {
		Long l = (0xffL & (long) bytes[offset + 0]) | (0xff00L & ((long) bytes[offset + 1] << 8))
				| (0xff0000L & ((long) bytes[offset + 2] << 16)) | (0xff000000L & ((long) bytes[offset + 3] << 24))
				| (0xff00000000L & ((long) bytes[offset + 4] << 32))
				| (0xff0000000000L & ((long) bytes[offset + 5] << 40));
		return (l == DataTypes.LONG_NULL ? null : l);
	}

	public static int getUShort(byte[] bytes, int p) {
		int s = (int) ((0xff & bytes[p + 0]) | (0xff00 & (bytes[p + 1] << 8)));
		return (s == DataTypes.SHORT_NULL ? null : s);
	}

	public static long getLong(byte[] bytes, int offset, int len) {
		if(len > 8) {
			len = 8;
		}
		
		long l = 0;
		switch (len) {
		case 8:
			l |= (0xff00000000000000L & ((long) bytes[offset + 7] << 56));
		case 7:
			l |= (0xff000000000000L & ((long) bytes[offset + 6] << 48));
		case 6:
			l |= (0xff0000000000L & ((long) bytes[offset + 5] << 40));
		case 5:
			l |= (0xff00000000L & ((long) bytes[offset + 4] << 32));
		case 4:
			l |= (0xff000000L & ((long) bytes[offset + 3] << 24));
		case 3:
			l |= (0xff0000L & ((long) bytes[offset + 2] << 16));
		case 2:
			l |= (0xff00L & ((long) bytes[offset + 1] << 8));
		case 1:
			l |= (0xffL & (long) bytes[offset + 0]);

		}

		return (l == DataTypes.LONG_NULL ? null : l);
	}

}
